﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using General.Core.Data;
using General.Entities.Models;
using General.Entities.ViewData.Chat;
using General.Framework;
using General.Services.Admin;
using General.Services.SystemConfig;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;

namespace General.Mvc.Chat
{
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    public class ChatHub:Hub
    {
        private readonly IAdminService adminService;
        private readonly IRepository<tc_user> tc_UserRepository;
        private readonly IRepository<tc_message> tc_MessageRepository;
        private readonly ISystemConfigService systemConfigService;

        public ChatHub(IAdminService adminService,
            IRepository<tc_user> tc_userRepository,
            IRepository<tc_message> tc_messageRepository,
            ISystemConfigService systemConfigService)
        {
            this.adminService = adminService;
            tc_UserRepository = tc_userRepository;
            tc_MessageRepository = tc_messageRepository;
            this.systemConfigService = systemConfigService;
        }


        /// <summary>
        /// 获取消息列表
        /// </summary>
        /// <param name="page">页数</param>
        /// <returns></returns>
        public async Task<string> CustomerGetChatMessageList(int page)
        {
            var customerClaim = await CustomerGetClaim();
            AjaxResult result = new AjaxResult();
            if (customerClaim.isadmin == 0) return result.Error("您没有权限");
            List<CustomerChatMessageListModel> list = new List<CustomerChatMessageListModel>();

            var limit = 20;
            var userlist = await tc_UserRepository.Table.Where(x=>x.ismsg==1).OrderByDescending(x=>x.lasttime).Skip((page - 1) * limit).Take(limit).ToListAsync();
            foreach (var item in userlist)
            {
                list.Add(await ChatMessageListProcess(item));
            }


            result.code = AjaxResultStateEnum.Ok;
            result.data = list;
            return JsonHelper.Serialize(result);
        }

        /// <summary>
        /// 新消息列表转换
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private async Task<CustomerChatMessageListModel> ChatMessageListProcess(tc_user item)
        {
            CustomerChatMessageListModel model = new CustomerChatMessageListModel();
            model.avatarUrl = item.userimg;
            model.badge = item.noreadnum;
            if (model.badge == 0)
            {
                model.badge = null;
            }
            model.date = item.lasttime.ToString("HH:mm");
            model.name = item.username + " " + item.ip;
            model.uid = item.id;
            //获取最新第一条消息
            //var msg = await tc_MessageRepository.Table.Where(x => x.uid == item.id && x.isuser == 1).OrderByDescending(x => x.id).FirstOrDefaultAsync();
            var msg = await tc_MessageRepository.Table.Where(x => x.uid == item.id).OrderByDescending(x => x.id).FirstOrDefaultAsync();
            if (msg != null)
            {
                if (msg.type > 2)
                {
                    model.message = "[文件]";
                }
                else if (msg.type == 2)
                {
                    model.message = msg.content;
                }
                else
                {
                    if (string.IsNullOrEmpty(msg.content))
                    {
                        model.message = "";
                    }
                    else
                    {
                        model.message = msg.content.Length > 16 ? msg.content.Substring(0, 16) + "..." : msg.content;
                    }
                   
                }
            }
            else
            {
                model.message = "新消息";
            }
            return model;
        }


        /// <summary>
        /// 客服端注册方法
        /// </summary>
        public async Task<string> CustomerRegister()
        {
            var customerClaim = await CustomerGetClaim();
            AjaxResult result = new AjaxResult();
            if (customerClaim.isadmin == 0) return result.Error("您没有权限");

            //注册connectionid和更新在线信息
            await RedisHelper.SetAsync("customerConnectionId", this.Context.ConnectionId);
            //var admin = await adminService.GetInfoById(1);
            await adminService.UpdateLoginTime(1);
            return result.Ok("success");
        }

        /// <summary>
        /// 检查客服端权限
        /// </summary>
        /// <returns></returns>
        private async Task<CustomerClaimModel> CustomerGetClaim()
        {
            //获取用户信息
            var user = this.Context.User;
            ClaimsIdentity claimsIdentity = (ClaimsIdentity)user.Identity;
            CustomerClaimModel model = new CustomerClaimModel();
            model.customerid = 0;
            model.token = "";
            model.isadmin = 0;
            foreach (var claim in claimsIdentity.Claims)
            {
                if (claim.Type == "customerid")
                {
                    model.customerid = Convert.ToInt32(claim.Value);
                }else if (claim.Type == "token")
                {
                    model.token = claim.Value;
                }else if (claim.Type == "isadmin")
                {
                    model.isadmin = Convert.ToInt32(claim.Value);
                }
            }
            return model;
        }

        /// <summary>
        /// 客服端获取基本信息
        /// </summary>
        /// <param name="aptuserid"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task<string> CustomerGetUserInfo(int uid)
        {
            var customerClaim = await CustomerGetClaim();
            AjaxResult result = new AjaxResult();
            if (customerClaim.isadmin == 0) return result.Error("您没有权限");
            var savedaymodel = await systemConfigService.GetConfigInfoByCode("usersavetime");
            var savedayval = Convert.ToInt32(savedaymodel.value);
            //获取客服信息
            var customer = await adminService.GetInfoById(1);
            var userInfo = await tc_UserRepository.getByIdAsync(uid);
            CustomerBaseModel model = new CustomerBaseModel();
            model.intime = userInfo.createtime.ToString("yyyy-MM-dd HH:mm:ss");
            //获取最大上传大小
            var maxuploadbyte = await systemConfigService.GetConfigInfoByCode("maxuploadbyte");
            model.maxUploadByte = Convert.ToInt64(maxuploadbyte.value);
            model.myImg = customer.headimg;
            model.myName = customer.username;
            model.uid = userInfo.id.ToString();
            model.userImg = userInfo.userimg;
            model.userName = userInfo.username;
            model.userStatus = userInfo.ip;


            result.code = AjaxResultStateEnum.Ok;
            result.data = model;
            return JsonHelper.Serialize(result);
        }

        /// <summary>
        /// 客户端设置消息已读
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public async Task<string> CustomerSetMsgRead(int uid)
        {
            var customerClaim = await CustomerGetClaim();
            AjaxResult result = new AjaxResult();
            if (customerClaim.isadmin == 0) return result.Error("您没有权限");
            var userInfo = await tc_UserRepository.getByIdAsync(uid);
            if (userInfo == null)
            {
                return result.Error("无此用户");
            }
            else
            {
                userInfo.isread = 1;
                userInfo.noreadnum = 0;
                tc_UserRepository.UpdateAsync(userInfo);
                return result.Ok("success");
            }
        }


        /// <summary>
        /// 客服端发送消息
        /// </summary>
        /// <param name="type"></param> //1.普通文本 2.表情 3.图片 
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task<string> CustomerSendMessage(int uid , int type, string message)
        {
            var customerClaim = await CustomerGetClaim();
            AjaxResult result = new AjaxResult();
            if (customerClaim.isadmin == 0) return result.Error("您没有权限");

            var addMessageModel = new tc_message()
            {
                content = message,
                intime = DateTime.Now,
                isuser = 0,
                type = 1,
                uid = uid
            };
            if (type == 1)
            {
                addMessageModel.type = 1;
            }
            else if (type == 2)
            {
                //message = message.Replace("<img","<img style='width: 17px;height:17px;vertical-align: sub;' ");
                message = "<img src='" + message + "' style='width: 17px;height:17px;vertical-align: sub;' />";
                addMessageModel.content = message;
                addMessageModel.type = 2;
            }
            else if (type == 3)
            {
                addMessageModel.type = 3;
            }


            await tc_MessageRepository.insertAsync(addMessageModel);

            var userInfo = await tc_UserRepository.getByIdAsync(uid);
            userInfo.ismsg = 1;
            userInfo.lasttime = DateTime.Now;
            tc_UserRepository.UpdateAsync(userInfo);




            //通知客户
            var customer = await adminService.GetInfoById(1);
            var newmsg = new ClientChatRecordItem()
            {
                avatarUrl = customer.headimg,
                content = addMessageModel.content,
                date = null,
                my = false,
                type = type==3?"image":"text",
                nickName = customer.username,
                imageUrl = type == 3 ? message : ""
            };
            var userConnectionId = await RedisHelper.GetAsync("uid-ConnectionId-" + uid);
            if (!string.IsNullOrEmpty(userConnectionId))
            {
                Clients.Client(userConnectionId).SendAsync("ClientOnMessage", newmsg);
            }

         


            return message;
        }



        /// <summary>
        /// 客户端获取基本信息
        /// </summary>
        /// <param name="aptuserid"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task<string> ClientGetBaseInfo()
        {
            //获取用户信息
            var user = this.Context.User;
            //this.Context.GetHttpContext().Request.
            ClaimsIdentity claimsIdentity = (ClaimsIdentity)user.Identity;
            var uid = 0;//用户编号
            var token = "";
            foreach (var claim in claimsIdentity.Claims)
            {
                if (claim.Type == "uid")
                {
                    uid = Convert.ToInt32(claim.Value);
                }
                if (claim.Type == "token")
                {
                    token = claim.Value;
                }
            }
            //记录ConnectionId
            var savedaymodel = await systemConfigService.GetConfigInfoByCode("usersavetime");
            var savedayval = Convert.ToInt32(savedaymodel.value);
            await RedisHelper.SetAsync("uid-ConnectionId-" + uid, this.Context.ConnectionId, 60 * 60 * 24 * savedayval);
           
            //获取客服信息
            var customer = await adminService.GetInfoById(1);
            var myInfo = await tc_UserRepository.getByIdAsync(uid);
            ClientBaseModel model = new ClientBaseModel();
            model.customerImg = customer.headimg;
            model.customerName = customer.username;
            var customertimeSpan = DateTime.Now - customer.lasttime;
            model.customerStatus = (customertimeSpan.TotalSeconds>=60)?"离线":"在线";
            model.intime = myInfo.createtime.ToString("yyyy-MM-dd HH:mm:ss");
            model.myImg = myInfo.userimg;
            model.myName = myInfo.username;
            model.uid = myInfo.id.ToString();

            //获取最大上传大小
            var maxuploadbyte = await systemConfigService.GetConfigInfoByCode("maxuploadbyte");
            model.maxUploadByte = Convert.ToInt64(maxuploadbyte.value);

            return JsonHelper.Serialize(model);
        }


        /// <summary>
        /// 客户端发送消息
        /// </summary>
        /// <param name="type"></param> //1.普通文本 2.表情 3.图片 
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task<string> ClientSendMessage(int type,string message)
        {
            var user = this.Context.User;
            ClaimsIdentity claimsIdentity = (ClaimsIdentity)user.Identity;
            var uid = 0;//用户编号
            var token = "";
            foreach (var claim in claimsIdentity.Claims)
            {
                if (claim.Type == "uid")
                {
                    uid = Convert.ToInt32(claim.Value);
                }
                if (claim.Type == "token")
                {
                    token = claim.Value;
                }
            }

            var addMessageModel = new tc_message()
            {
                content = message,
                intime = DateTime.Now,
                isuser = 1,
                type = 1, uid = uid
            };
            if (type == 1)
            {
                addMessageModel.type = 1;
            }
            else if (type == 2)
            {
                //message = message.Replace("<img","<img style='width: 17px;height:17px;vertical-align: sub;' ");
                message = "<img src='" + message + "' style='width: 17px;height:17px;vertical-align: sub;' />";
                addMessageModel.content = message;
                addMessageModel.type = 2;
            }
            else if (type == 3)
            {
                addMessageModel.type = 3;
            }
            


           
            await tc_MessageRepository.insertAsync(addMessageModel);


            //设置消息未读
            var userInfo = await tc_UserRepository.getByIdAsync(uid);
            userInfo.ismsg = 1;
            userInfo.isread = 0;
            userInfo.noreadnum = userInfo.noreadnum + 1;
            userInfo.lasttime = DateTime.Now;
            tc_UserRepository.UpdateAsync(userInfo);


            //离线回复
            var showOfflineTip = await systemConfigService.GetConfigInfoByCode("showOfflineTip");
            if (Convert.ToInt32(showOfflineTip.value)==1)
            {
                //判断客服是否在线
                var customer = await adminService.GetInfoById(1);
                var customertimeSpan = DateTime.Now - customer.lasttime;
                var isOnline = (customertimeSpan.TotalSeconds >= 60) ? false : true;
                if (!isOnline)
                {
                    var offlineTip = await systemConfigService.GetConfigInfoByCode("offlineTip");
                    var offlineMsg = new ClientChatRecordItem()
                    {
                        avatarUrl = customer.headimg,
                        content = offlineTip.value,
                        date = null,
                        my = false,
                        type = "text",
                        nickName = customer.username
                    };
                    tc_MessageRepository.insertAsync(new tc_message() { content = offlineTip.value, intime = DateTime.Now, isuser = 0, type = 1, uid=uid });
                    Clients.Caller.SendAsync("ClientOnMessage", offlineMsg);
                }
            }

            //通知客服
            //...
            
            ClientSendNoticeToCustomer(addMessageModel, userInfo);


            return message;
        }


        /// <summary>
        /// 客户端发送消息给客服端
        /// </summary>
        /// <returns></returns>
        private async Task ClientSendNoticeToCustomer(tc_message message, tc_user user)
        {
            //获取客服端connectionid
            var customerConnectionId = await RedisHelper.GetAsync("customerConnectionId");
            if (string.IsNullOrEmpty(customerConnectionId))
            {
                return;
            }
            //ClientChatRecordItem recordModel = new ClientChatRecordItem();
            CustomerChatMessageListModel customerChat = new CustomerChatMessageListModel();
            customerChat.avatarUrl = user.userimg;
            customerChat.badge = 1;
            customerChat.date = DateTime.Now.ToString("HH:mm");
            customerChat.name = user.username + " "+user.ip;
            customerChat.uid = user.id;
            if (message.type > 2)
            {
                customerChat.message = "[文件]";
            }
            else if (message.type == 2)
            {
                customerChat.message = message.content;
            }
            else
            {
                if (string.IsNullOrEmpty(message.content))
                {
                    return;
                }
                customerChat.message = message.content; //message.content.Length > 16 ? message.content.Substring(0, 16) + "..." : message.content;
            }
            //发送给客服端
            await Clients.Client(customerConnectionId).SendAsync("CustomerOnNotice", customerChat);

            //发送新消息
            var newMsg = new ClientChatRecordItem()
            {
                avatarUrl = user.userimg,
                content = customerChat.message,
                date = null,
                my = false,
                type = message.type == 3?"image":"text",
                nickName = user.username,
                imageUrl = message.type == 3 ? message.content:""
            };
            await Clients.Client(customerConnectionId).SendAsync("CustomerOnMessage-"+ user.id, newMsg);

        }

        /// <summary>
        /// 获取聊天记录
        /// </summary>
        /// <param name="indexLocation"></param>
        /// <returns></returns>
        public async Task<string> ClientGetChatRecord(int indexLocation)
        {
            var user = this.Context.User;
            ClaimsIdentity claimsIdentity = (ClaimsIdentity)user.Identity;
            var uid = 0;//用户编号
            var token = "";
            foreach (var claim in claimsIdentity.Claims)
            {
                if (claim.Type == "uid")
                {
                    uid = Convert.ToInt32(claim.Value);
                }
                if (claim.Type == "token")
                {
                    token = claim.Value;
                }
            }
            var recordcountModel = await systemConfigService.GetConfigInfoByCode("recordcount");
            var recordcount = Convert.ToInt32(recordcountModel.value);

            ClientChatRecordModel model = new ClientChatRecordModel();
            model.indexLocation = 0;
            model.list = new List<ClientChatRecordItem>();
            var query = from m in tc_MessageRepository.Table
                             where m.uid == uid
                             orderby m.id descending
                             select new tc_message() { id = m.id, uid = m.uid, intime=m.intime, content =m.content, isuser=m.isuser, type =m.type };
            if (indexLocation>0)
            {
                query = query.Where(x=>x.id < indexLocation);
            }
            var selectData = await query.Take(recordcount).ToListAsync();
            selectData = selectData.OrderBy(x=>x.id).ToList();//倒序
            var customer = await adminService.GetInfoById(1);
            var myInfo = await tc_UserRepository.getByIdAsync(uid);
            for (var i = 0; i< selectData.Count;i++)
            {
                ClientChatRecordItem item = new ClientChatRecordItem();
                item.content = selectData[i].content;
                if (selectData[i].isuser==1)
                {
                    item.avatarUrl = myInfo.userimg;
                    item.my = true;
                    item.nickName = myInfo.username;
                }
                else
                {
                    item.avatarUrl = customer.headimg;
                    item.my = false;
                    item.nickName = customer.username;
                }
                if (selectData[i].type==1 || selectData[i].type == 2)
                {
                    item.type = "text";
                }
                else if(selectData[i].type == 3)
                {
                    item.type = "image";
                }
                item.imageUrl = selectData[i].content;
                if (i==0)
                {
                    model.indexLocation = selectData[i].id;
                    var spantime = DateTime.Now - selectData[i].intime;
                    if (spantime.TotalDays>1)
                    {
                        item.date = selectData[i].intime.ToString("MM-dd HH:mm");
                    }
                    else
                    {
                        item.date = selectData[i].intime.ToString("HH:mm");
                    }
                }
                else
                {
                    if (i - 1 >= 0)
                    {
                        var spantime = selectData[i].intime - selectData[i - 1].intime;
                        if (spantime.TotalMinutes > 5)
                        {
                            item.date = selectData[i].intime.ToString("HH:mm");
                        }
                        else
                        {
                            item.date = null;
                        }
                    }
                }
                model.list.Add(item);
            }

            //欢迎语
            var showHelloModel = await systemConfigService.GetConfigInfoByCode("showHello");
            if (Convert.ToInt32(showHelloModel.value) == 1)
            {
                var helloContentModel = await systemConfigService.GetConfigInfoByCode("helloContent");

                model.list.Add(new ClientChatRecordItem() {
                     avatarUrl = customer.headimg, content = helloContentModel.value, date=null, my = false, type="text", nickName = customer.username
                });
            }

            return JsonHelper.Serialize(model);
        }


        /// <summary>
        /// 客服端获取聊天记录
        /// </summary>
        /// <param name="indexLocation"></param>
        /// <returns></returns>
        public async Task<string> CustomerGetChatRecord(int uid,int indexLocation)
        {
            var customerClaim = await CustomerGetClaim();
            AjaxResult result = new AjaxResult();
            if (customerClaim.isadmin == 0) return result.Error("您没有权限");

            var recordcountModel = await systemConfigService.GetConfigInfoByCode("recordcount");
            var recordcount = Convert.ToInt32(recordcountModel.value);

            ClientChatRecordModel model = new ClientChatRecordModel();
            model.indexLocation = 0;
            model.list = new List<ClientChatRecordItem>();
            var query = from m in tc_MessageRepository.Table
                        where m.uid == uid
                        orderby m.id descending
                        select new tc_message() { id = m.id, uid = m.uid, intime = m.intime, content = m.content, isuser = m.isuser, type = m.type };
            if (indexLocation > 0)
            {
                query = query.Where(x => x.id < indexLocation);
            }
            var selectData = await query.Take(recordcount).ToListAsync();
            selectData = selectData.OrderBy(x => x.id).ToList();//倒序
            var customer = await adminService.GetInfoById(1);
            var myInfo = await tc_UserRepository.getByIdAsync(uid);
            for (var i = 0; i < selectData.Count; i++)
            {
                ClientChatRecordItem item = new ClientChatRecordItem();
                item.content = selectData[i].content;
                if (selectData[i].isuser == 1)
                {
                    item.avatarUrl = myInfo.userimg;
                    item.my = false;
                    item.nickName = myInfo.username;
                }
                else
                {
                    item.avatarUrl = customer.headimg;
                    item.my = true;
                    item.nickName = customer.username;
                }
                if (selectData[i].type == 1 || selectData[i].type == 2)
                {
                    item.type = "text";
                }
                else if (selectData[i].type == 3)
                {
                    item.type = "image";
                }
                item.imageUrl = selectData[i].content;
                if (i == 0)
                {
                    model.indexLocation = selectData[i].id;
                    var spantime = DateTime.Now - selectData[i].intime;
                    if (spantime.TotalDays > 1)
                    {
                        item.date = selectData[i].intime.ToString("MM-dd HH:mm");
                    }
                    else
                    {
                        item.date = selectData[i].intime.ToString("HH:mm");
                    }
                }
                else
                {
                    if (i - 1 >= 0)
                    {
                        var spantime = selectData[i].intime - selectData[i - 1].intime;
                        if (spantime.TotalMinutes > 5)
                        {
                            item.date = selectData[i].intime.ToString("HH:mm");
                        }
                        else
                        {
                            item.date = null;
                        }
                    }
                }
                model.list.Add(item);
            }
            result.code = AjaxResultStateEnum.Ok;
            result.data = model;
            return JsonHelper.Serialize(result);
        }

    }
}
